﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;

[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)]
[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]

namespace IBS2ibsImport
{
    public class Impersonation
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource,
            int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, IntPtr* Arguments);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
            int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

        public static WindowsImpersonationContext impersonatedUser;
        public static IntPtr tokenHandle;

        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public static void Logon(string userName, string domainName, string password)
        {
            tokenHandle = new IntPtr(0);
            IntPtr dupeTokenHandle = new IntPtr(0);
            try
            {
                const int LOGON32_PROVIDER_DEFAULT = 0;
                const int LOGON32_LOGON_INTERACTIVE = 2;
                tokenHandle = IntPtr.Zero;

                bool returnValue = LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);

                if (false == returnValue)
                {
                    int ret = Marshal.GetLastWin32Error();
                    throw new System.ComponentModel.Win32Exception(ret);
                }

                // Используемый дескриптор токена возвратить LogonUser-у.
                WindowsIdentity newId = new WindowsIdentity(tokenHandle);
                impersonatedUser = newId.Impersonate();
            }
            catch (Exception ex) { }
        }

        public static void Logoff()
        {
            // выйти из-под учетной записи
            impersonatedUser.Undo();

            // освобождаем токены
            if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle);

        }
    }
}
